#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:Zhangcl
import json
import select
import socket
import queue
import os
from conf import  setting

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

server_addr = (setting.FTP_HOST,setting.FTP_PORT)
server.bind(server_addr)
server.listen(10)

server.setblocking(False)
inputs = [ server, ]
outputs = []
message_dict ={}

while True:
    readable,writeable,exceptional = select.select(inputs,outputs,inputs)
    #print(inputs,outputs,message_dict)
    #readable 存放链接,writeable存放需要返回数据的链接
    for r in readable:
        if r is server: #代表一个新连接
            conn, addr = r.accept()
            print('new connection from', addr)
            conn.setblocking(False)
            inputs.append(conn)
        else: #已经存在的连接请求
            if r not in outputs:
                try:
                    data = r.recv(1024)
                    if data:
                        headle_data = json.loads(data.decode())
                        if headle_data['action'] == 'get':
                            send_file = os.path.join(setting.USER_FILE_PATH,headle_data['filename'])
                            if os.path.isfile(send_file):
                                file_siez = os.path.getsize(send_file)
                                r.send(str(file_siez).encode())
                                file_send = open(send_file,'rb')
                                send_size = 0
                                message_dict[r] = queue.Queue()#初始化一个队列，后面存要返回给这个客户端的数据
                                while send_size < file_siez:
                                    send_data = file_send.read(setting.read_size)
                                    message_dict[r].put(send_data)#将需要返回的数据信息放入队列
                                    send_size += len(send_data)
                                outputs.append(r)#将需要返回的连接put进队列
                                file_send.close()
                                for w in outputs:  # 要返回给客户端的连接列表
                                    w.setblocking(True)
                                    if message_dict[w]:
                                        while message_dict[w].qsize() != 0:
                                            send_to_location = message_dict[w].get()
                                            w.send(send_to_location)
                                        else:
                                            outputs.remove(w)
                        if headle_data['action'] == 'put':
                                message_dict[r] = queue.Queue()#初始化一个队列，将用户操作信息存入
                                message_dict[r].put(headle_data)
                                outputs.append(r)
                                r.send(b'1') #防止粘包
                    else:
                        raise Exception('连接断开')
                        if r in outputs:
                            outputs.remove(r)
                        inputs.remove(r)
                        del message_dict[r]

                except Exception as e:
                    print(e)
                    inputs.remove(r)

            else:
                head_data = message_dict[r].get() #将需要进行的put操作信息取出
                print(head_data)
                save_path = os.path.join(setting.USER_FILE_PATH,head_data['filename'])
                file_obj = open(save_path,'wb')
                received_size = 0
                r.setblocking(True)
                while received_size < head_data['size']:
                    recv_data = r.recv(4096)
                    file_obj.write(recv_data)
                    received_size += len(recv_data)
                else:
                    file_obj.close()
                    outputs.remove(r)
                    del message_dict[r]
                    print('done')
